join: 1.37x faster on paired input, 2.5x faster than GNU, by skipping the locale compare - #14213
Conversation
In the default check-order mode the ordering warning is only emitted once unpaired lines have been seen (has_unpaired=true). Calling input.compare() (which may invoke ICU locale_cmp) on every line regardless was wasteful: on a 1M-line file with a locale active this accounts for ~35% of the total runtime. Early-return before the compare() call when the result cannot possibly trigger a warning. Benchmarks (fr_FR.UTF-8, 1M lines): Before: 814 ms (1.90x slower than GNU join) After: 523 ms (1.25x slower than GNU join)
Merging this PR will improve performance by 4.34%
Performance Changes
Tip Curious why performance improved? Comment Comparing Footnotes
|
|
GNU testsuite comparison: |
|
hyperfine results 1M-line inputs, release builds, Fully paired (1M x 1M), fr_FR.UTF-8
Fully paired (1M x 1M), LC_ALL=C
Half unpaired (1M x 500k), fr_FR.UTF-8
|
In the default check-order mode the ordering warning is only emitted once unpaired lines have been seen (
has_unpaired=true). Callinginput.compare()(which may invoke ICUlocale_cmp) on every line regardless was wasteful: on a 1M-line file with a locale active this accounts for ~35% of the total runtime.Early-return before the
compare()call when the result cannot possibly trigger a warning.Benchmarks (fr_FR.UTF-8, 1M lines)
GNU join: ~432 ms
The existing
join_french_localeandjoin_unicode_localeCodSpeed benchmarks cover this path.